package cn.chrilwe.pigpig.im.rule;

import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 一致性hash算法
 * @author chrilwe
 * @date 2020-9-20
 */
public class ConsistenceHashBalanceRule {
	
	private List<String> serverAddressList;
	
	private TreeMap<Integer, String> treeMap;
	
	//虚拟节点数量
	private final int virtualNodes = 10;
	
	public ConsistenceHashBalanceRule(List<String> serverAddressList) {
		this.serverAddressList = serverAddressList;
		if(serverAddressList == null || serverAddressList.size() == 0) {
			throw new RuntimeException("serverAddressList 不能为空");
		}
		treeMap = new TreeMap<Integer, String>();
		for(int i = 0; i < virtualNodes; i++) {
			for (String address : serverAddressList) {
				String key = address + i;
				treeMap.put(hash(key), address);
			}
		}
	}
	
	@SuppressWarnings("unused")
	private int hash(String key) {
		final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < key.length(); i++)
            hash = (hash ^ key.charAt(i)) * p;
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;
 
        // 如果算出来的值为负数则取其绝对值
        if (hash < 0)
            hash = Math.abs(hash);
        return hash;
	}

	public String choose(String key) {
		if(serverAddressList == null || serverAddressList.size() == 0
				|| treeMap == null) {
			throw new RuntimeException("serverAddressList 不能为空");
		}
		SortedMap<Integer, String> sortMap = treeMap.tailMap(hash(key));
		if(sortMap != null && sortMap.size() == 0) {
			return treeMap.get(treeMap.firstKey());
		} else {
			if(sortMap != null) {
				return sortMap.get(sortMap.firstKey());
			}
		}
		return null;
	}
}
